/**
 * Project Name:jbase
 * File Name:HttpResponse.java
 * Package Name:jbase.project.system.net.http.websearch
 * Date:2017年4月30日下午6:32:21
 * Copyright (c) 2017, chenzhou1025@126.com All Rights Reserved.
 *
*/

package jbase.project.system.net.http.websearcher;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import jbase.project.system.core.support.LocalService;
import jbase.project.system.util.IOUtil;

/**
 * ClassName:HttpResponse <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * Date: 2017年4月30日 下午6:32:21 <br/>
 * 
 * @author Licheng
 * @version
 * @since JDK 1.8
 * @see
 */
public class HttpResponse {

	private Map<String, List<String>> headers;
	private byte[] body;
	private volatile String bodyCharset = null;
	private volatile String contentEncoding = null;

	public HttpResponse(Map<String, List<String>> headers, byte[] body) {
		this.headers = headers;
		System.out.println(headers);
		this.body = body;
	}

	public String getContentEncoding() {
		if (this.contentEncoding != null) {
			return this.contentEncoding;
		} else {
			Set<String> headerKeySet = headers.keySet();
			for (String header : headerKeySet) {
				if (header != null && header.toUpperCase().equals("CONTENT-ENCODING")) {
					List<String> items = headers.get(header);
					for (String item : items) {
						this.contentEncoding = item;
						return this.contentEncoding;
					}
				}
			}
		}
		return null;
	}

	public String getCharet() {
		if (bodyCharset != null) {
			return bodyCharset;
		}

		Set<String> headerKeySet = headers.keySet();
		for (String header : headerKeySet) {
			if (header != null && header.toUpperCase().equals("CONTENT-TYPE")) {
				List<String> items = headers.get(header);
				for (String item : items) {
					String find = LocalService.search(item,
							"[Cc][Hh][Aa][Rr][Ss][Ee][Tt]\\=([a-z]|[A-Z]|[0-9]|[\\-])+");
					if (find != null) {
						String[] splits = find.split("\\=");
						this.bodyCharset = splits[1];
						return this.bodyCharset;
					}
				}
			}
		}

		Runnable run = new Runnable() {
			public void run() {
				Pattern pattern = Pattern
						.compile("<\\s*(M|m)(E|e)(T|t)(a|A)\\s+(h|H)(t|T)[Tt][Pp]-[eE][Qq][uU][Ii][vV][^>]*/?>");
				Matcher matcher = pattern.matcher(new String(getBody()));
				FIND_MAIN: while (matcher.find()) {
					String meta = matcher.group();
					if (Pattern.matches(
							".*\\s+(h|H)(t|T)[Tt][Pp]-[eE][Qq][uU][Ii][vV]\\s*=\\s*\\\"[Cc][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]\\\".*",
							meta)) {
						Pattern charsetPattern = Pattern
								.compile("[Cc][Hh][Aa][Rr][Ss][Ee][Tt]\\s*=([a-z]|[A-Z]|\\d|-)+");
						Matcher charsetMatcher = charsetPattern.matcher(meta);
						while (charsetMatcher.find()) {
							String charSet = charsetMatcher.group();
							String value = charSet.split("=").length > 1 ? charSet.split("=")[1] : null;
							bodyCharset = value;
							break FIND_MAIN;
						}
					}
				}
			}
		};
		Thread work = new Thread(run);
		work.setDaemon(true);
		work.start();
		try {
			work.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return bodyCharset;
	}

	public List<String> getLinks() {
		return getTag("a");
	}

	public List<String> getImgs() {
		return getTag("img");
	}

	public static class FindTagWorker implements Runnable {
		public List<String> tags;
		public String tagName;
		public String text;

		public FindTagWorker(List<String> tags, String tagName, String text) {
			this.tags = tags;
			this.tagName = tagName;
			this.text = text;
		}

		public void run() {
			String reg = "";
			for (char ch : tagName.toCharArray()) {
				reg += "[" + new String(new char[] { ch }).toUpperCase() + new String(new char[] { ch }).toLowerCase()
						+ "]";
			}
			Pattern tagPattern = Pattern.compile("<[\\s\\r\\n]*" + reg + "(\\s|\\r|\\n)+[^>]*>");
			Matcher tagMatcher = tagPattern.matcher(text);
			while (tagMatcher.find()) {
				tags.add(tagMatcher.group());
			}
		}
	};

	public List<String> getTag(String tagName) {
		List<String> tags = Collections.synchronizedList(new ArrayList<String>());
		FindTagWorker worker = new FindTagWorker(tags, tagName, toString());
		Thread t = new Thread(worker);
		t.setDaemon(true);
		t.start();
		try {
			t.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return tags;
	}

	public Map<String, List<String>> getHeader() {
		return headers;
	}

	public void setHeader(Map<String, List<String>> header) {
		this.headers = headers;
	}

	public byte[] getBody() {
		return body;
	}

	public void setBody(byte[] body) {
		this.body = body;
	}

	public String bodyToString() {
		String charSet = getCharet();
		String contentEncoding = getContentEncoding();
		try {
			if (contentEncoding == null) {
				if (charSet != null) {
					return new String(body, charSet);
				} else {
					return new String(body);
				}
			} else if (contentEncoding.toLowerCase().equals("gzip")) {
				GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(body));
				byte[] data = IOUtil.readData(gzi);
				if (charSet != null) {
					return new String(data, charSet);
				} else {
					return new String(data);
				}
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace(System.out);
		}
		return null;
	}

	public String toString() {
		return bodyToString();
	}
}